package com.ruoci.redis.utils.rsa;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class RsaUtils {

    /**
     * 类型
     */
    public static final String ENCRYPT_TYPE = "RSA";

    /**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";

    /**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 公钥加密
     *
     * @param content   要加密的内容
     * @param publicKey 公钥，可以是 PublicKey 对象或 Base64 编码的公钥字符串
     * @return 加密后的字符串
     */
    public static String encrypt(String content, Object publicKey) {
        try {
            RSA rsa = publicKey instanceof PublicKey ? new RSA(null, (PublicKey) publicKey) : new RSA(null, (String) publicKey);
            return rsa.encryptBase64(content, KeyType.PublicKey);
        } catch (Exception e) {
            log.error("公钥加密异常: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 私钥解密
     *
     * @param content    要解密的内容
     * @param privateKey 私钥，可以是PrivateKey 对象或 Base64 编码的私钥字符串
     * @return 解密后的字符串
     */
    public static String decrypt(String content, Object privateKey) {
        try {
            RSA rsa = privateKey instanceof PrivateKey ? new RSA((PrivateKey) privateKey, null) : new RSA((String) privateKey, null);
            return rsa.decryptStr(content, KeyType.PrivateKey);
        } catch (Exception e) {
            log.error("私钥解密异常: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 获取公私钥 - 请获取一次后保存公私钥使用
     *
     * @return 公私钥的 Map
     */
    public static Map<String, String> generateKeyPair() {
        try {
            KeyPair pair = SecureUtil.generateKeyPair(ENCRYPT_TYPE);
            PrivateKey privateKey = pair.getPrivate();
            PublicKey publicKey = pair.getPublic();
            // 获取公钥和私钥的编码格式（通过该编码格式可以反过来生成公钥和私钥对象）
            byte[] pubEncBytes = publicKey.getEncoded();
            byte[] priEncBytes = privateKey.getEncoded();
            // 把公钥和私钥的编码格式转换为Base64文本
            String pubEncBase64 = Base64.getEncoder().encodeToString(pubEncBytes);
            String priEncBase64 = Base64.getEncoder().encodeToString(priEncBytes);
            Map<String, String> map = new HashMap<>(2);
            map.put(PUBLIC_KEY, pubEncBase64);
            map.put(PRIVATE_KEY, priEncBase64);
            return map;
        } catch (Exception e) {
            log.error("生成密钥对异常: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 生成 PEM 文件到指定路径
     *
     * @param publicKeyPemPath  公钥 PEM 文件路径
     * @param privateKeyPemPath 私钥 PEM 文件路径
     */
    public static void generatePemFiles(String publicKeyPemPath, String privateKeyPemPath) {
        Map<String, String> keyPair = generateKeyPair();
        if (keyPair != null) {
            try {
                String publicKeyPem = convertToPem(keyPair.get(PUBLIC_KEY), "PUBLIC KEY");
                String privateKeyPem = convertToPem(keyPair.get(PRIVATE_KEY), "PRIVATE KEY");
                try (FileWriter pubKeyWriter = new FileWriter(publicKeyPemPath);
                     FileWriter priKeyWriter = new FileWriter(privateKeyPemPath)) {
                    pubKeyWriter.write(publicKeyPem);
                    priKeyWriter.write(privateKeyPem);
                }
            } catch (IOException e) {
                log.error("生成 PEM 文件异常: {}", e.getMessage());
            }
        }
    }

    /**
     * 获取密钥
     *
     * @param keyPemPath 密钥文件路径
     * @return 密钥的 Base64 文本
     */
    public static String loadKey(String keyPemPath) {
        ClassPathResource resource = new ClassPathResource(keyPemPath);
        try (FileReader reader = new FileReader(resource.getFile())) {
            StringBuilder content = new StringBuilder();
            char[] buffer = new char[1024];
            int numRead;
            while ((numRead = reader.read(buffer)) != -1) {
                content.append(buffer, 0, numRead);
            }
            String key = content.toString();
            return key.replaceAll("-----BEGIN .* KEY-----", "")
                    .replaceAll("-----END .* KEY-----", "")
                    .replaceAll("\\s+", "");
        } catch (IOException e) {
            log.error("读取 PEM 文件异常: {}", e.getMessage());
        }
        return null;
    }

    private static String convertToPem(String key, String keyType) {
        return "-----BEGIN " + keyType + "-----\n" + key + "\n-----END " + keyType + "-----";
    }

    public static void main(String[] args) {
//        String publicKeyPath = "dh_public_key.pem";
//        String privateKeyPath = "dh_private_key.pem";
//        generatePemFiles(publicKeyPath, privateKeyPath);
//        System.out.println("PEM 文件已生成到以下路径:");
//        System.out.println("公钥: " + publicKeyPath);
//        System.out.println("私钥: " + privateKeyPath);
        String count ="{\n" +
                "\t\"empTempInfos\": [{\n" +
                "\t\t\"rpMonth\": \"202411\",\n" +
                "\t\t\"acntmCode\": \"11111138M\",\n" +
                "\t\t\"empCode\": \"110101199001018797\",\n" +
                "\t\t\"empName\": \"李小明\",\n" +
                "\t\t\"idcardType\": \"1\",\n" +
                "\t\t\"idcardNo\": \"110101199001018797\",\n" +
                "\t\t\"nationalityCode\": \"CN\",\n" +
                "\t\t\"depOrgName\": \"IT部门\",\n" +
                "\t\t\"postName\": \"测试部门\",\n" +
                "\t\t\"postLevelCode\": \"36\",\n" +
                "\t\t\"educationLbackgroundCode\": \"30\",\n" +
                "\t\t\"workStatusFlag\": \"1\",\n" +
                "\t\t\"oneOrgNterpriseFlag\": \"1\",\n" +
                "\t\t\"seniorExecutiveFlag\": \"1\",\n" +
                "\t\t\"externalDirectorFlag\": \"1\",\n" +
                "\t\t\"managerFlag\": \"1\",\n" +
                "\t\t\"managerCode\": \"3\",\n" +
                "\t\t\"empTechnologyFlag\": \"1\",\n" +
                "\t\t\"empTechnologyCode\": \"5\",\n" +
                "\t\t\"workTechnologyFlag\": \"1\",\n" +
                "\t\t\"empOverseasCode\": \"1\",\n" +
                "\t\t\"freshGraduatesFlag\": \"1\",\n" +
                "\t\t\"pretaxsalary\": 0.00,\n" +
                "\t\t\"annualsalary\": 0.00,\n" +
                "\t\t\"performancesalary\": 0.00,\n" +
                "\t\t\"incentiveincome\": 0.00,\n" +
                "\t\t\"otherincome\": 0.00,\n" +
                "\t\t\"subsidies\": 0.00,\n" +
                "\t\t\"delayedpayment\": 0.00,\n" +
                "\t\t\"specialrewards\": 0.00,\n" +
                "\t\t\"incentivesFlag\": \"1\",\n" +
                "\t\t\"longIncentiveTools\": \"a\",\n" +
                "\t\t\"exerciseincome\": 0.00,\n" +
                "\t\t\"totalincome\": 0.00,\n" +
                "\t\t\"remarks\": \"备注测试\"\n" +
                "\t}]\n" +
                "}";
        //String publicKey = loadKey("dh_public_key.pem");
//        String encrypt = encrypt(count, "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6kezfUqIWd42fRfNyxvzcnY9zVLVnT0n1H0sAEtn1jzEkxPLhlw/V0k5LnODOGdd8lk5M4WYSrlE6k6fWOu94DquCUUruzh5VPqq1pyxk5XHjJELD/ZS6PxiKUPvO0eYnrMdylBMx+pZiZlDH81d7yaAi5/2GvcP67YMdRj3FQIDAQAB");
//        System.out.println(encrypt);
//        String privateKey = loadKey("dh_private_key.pem");
        String decrypt = decrypt("lxbbXRaZc80LfWxsNhhHhvDP0i24QUr4/FFXUpjRdH/eKOBCHUkcPKboNOVplQdk5w6eaT49ehjzTIQ/D9tDHVtxvbJIPJ1yIUEmzb76pVNn4bp+ZA9VLgbaOTW6kgPxtCxNcYT6NDXqBG1sCKv7br2Cc7uo/CMXipTbPVEKKxidYSkyvukioPf1HYtfRFj21FykseJP8LmKXn5LNHVMctKzgFjvfusPv7jDcdnSYJohXWo4jlv4zlumT+TmgxtcXUdVEJqei/VWT+j/cCOYT6nWqlqYwwhJlaYGwBC0b77QfYgR07eFNnYBOpXateA/Dwmx3sHuCTAgaL+zOIPic13harfvG8yGYv/pyn+Lr/nEOKnfNxDmoFRBqM01KDEQuSPtG2SbO3ztUnz5upvvrJBJiPd73kt/65clxCAoKEglteC0QtGAVTRonzOXRV6uqzxVbZRomQK2UCjKyF6eaY6F4oO0vwUQ6HxIuAEBPUCN7uamA3lt4oGxV8bbaFqVCpbgpjBimt+LpElkIXM7n0J+N0cU5/TKuEhap/T5tgvCrL9DDhxnDobKkNRcjKWrfUxN4WCvT2zB7fxcOioy3i4z5COhFdhxCSLucT3symN24wHVH+h9FJw1JjeVgHqNMgRlXkADG7NuDM9t/AMTcgORerWEGkD8KAqAQ4zA/llJHrpRbrZrrz9b5kgaIGOF3GwxXTDcMqpJ99vRalnEPmvQ6xqZJ4X1wf90WZdojwwHOfG79DBDcd03ZmILP9oiT/aJDrp5dNiUulD1nMhTy2HdO4266gTJmFlAh47qWBO7tlJPgxzbo4Oq2JZ/S5ZPFnN+w8yDfdGdaJAf/o5HWp2p50BElZeCs+uSG3u1YJjKravHYTpUyL9CrCAbpajYz0Th4fdeEai8dFAItv/mGYPwmOjopR6aOnZtDF1X5y0vvf3szyU7RXwNp6c00ftEi+/h/Q2zwUQ+ThdLngHOvhCNuSHSEGEGMBE7QZ9KkWPB1LZfPzaDF/4TAN1XgzaIYjnyW4CR4ZLGL57432d8KrO9e9JgJvYuClAoe5UoXyb/8b36/nDm9DXv8uav5rmvA5IQOEcxFnhSvKV4+6rxQQ+tCWjARLXm8hYvZ0BgEQEowzuifquKgjXBivATFQN2pcBd1YkzX7LVovOx9vB/RjL92rsQzGvLPILNxe8MFesccpCmklUqkCETiNy3tUGUHcynZ0EHeUma/GDPNCgFVCA9ZjUYTniDcFKboaCXnpbvrobptm82gCBeTqyBYucocXxjYcmzThOFHd2kNiRv2HvWl5DdFfFk4n4o4L9lBdWkF75hfTqHv309wFDp3az3Ya0Vtg1CLc4p+roHaKw46RUmeJfFehez17tRw03Us/corE55GmJ7LBrvA67LrblJ6JJBYMJ0m4auPPrH8tjMEJ1flNk1Zu+QJD07S6L5gFS/zdIen0MaBZ+ynKziqI9x6IyqK0gp76X5VYfeAw4oE1oJo8W6p8W7Uh/N77mAe7/SA0bV24il1w6u3omsbYNl",
                "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALHqR7N9SohZ3jZ9F83LG/Nydj3NUtWdPSfUfSwAS2fWPMSTE8uGXD9XSTkuc4M4Z13yWTkzhZhKuUTqTp9Y673gOq4JRSu7OHlU+qrWnLGTlceMkQsP9lLo/GIpQ+87R5iesx3KUEzH6lmJmUMfzV3vJoCLn/Ya9w/rtgx1GPcVAgMBAAECgYBXzW4bR4774ZYHwA56Um115Jwz/duObm4a9QPdLjwIf7M3s/oF7EYkQFhzrtf0/2YL+ClOUH3y3ZW3TAcHHuQf2rWW8H44QWVUO9iJiOy3mOPuylDnAF+474lVG22ri1FQN7KnOC2GwLVBXcOO+ueHN8DBAJVTbHMbFH19xnaoIQJBAOMks3858ONi5uFEuMdZeaNVnAH5eWPqzjGC+IoOMtxZA5NQujrnh2zlP3Mbmpecfejk1kZybrs9+OKzkSkIW00CQQDIhIxeEurfEm9GkID64Qjk1TMA3uflycvhPY2VFpL1dKchacpM4F6ZXhlwS/4jgY2oNXQ3Bd+xa0ml3igoGlbpAkEAk1E1XZmtozx887OHiDt+ybF3ekxcL7KVQsVn/toQoJrW18+uyQ9q5PSWP0iy7gvgGZF5a71CFgyuhBHkXtF9rQJAafK/SCWuvFc9PIe13tlwnZiY7mjZFu1dMJIZcSEQXWlZtan0HlKfKWIzBsbgbVpSwwIbecc8vr31mBKeHTJtoQJAME7GJqBdfunWaxxGKXAGGLQndGObj4RDUWRKO16JLfwBKTCoXeQAma1wHbv4Dq412ErzKaS9HaQpJ89MGHDcDg==");
        System.out.println("加密的内容: " + decrypt);
    }
}
